﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Xml.Linq;
//
using PerceptiveMCAPI.Types;
//
namespace PerceptiveMCAPI
{
   public class apiSerial
   {
      // ------------------------------------------
      internal static string ProcessRequest(
         Api_BaseInput input, Dictionary<string, string> parameters,
         out string request
         )
      {
         // ----------- setup base request
         string outputType = input.api_OutputType.ToString().ToLower();
         string baseURL = string.Format( "{0}/?output={1}", input.SubmitUrl, outputType );

         StringBuilder sb = new StringBuilder( baseURL );
         sb.Append( "&method=" + input.api_Method );
         // ===============================================================
         HttpWebRequest wRequest;
         // ----------- build request data based on method type
         // -- GET --
         string GET_request = "";
         if ( input.api_MethodType == EnumValues.MethodType.GET )
         {
            foreach ( KeyValuePair<string, string> parm in parameters )
            {
               if ( input.api_EncodeRequest )
                  sb.Append( string.Format( "&{0}={1}", parm.Key, HttpUtility.UrlEncode( parm.Value ) ) );
               else
                  sb.Append( string.Format( "&{0}={1}", parm.Key, parm.Value ) );
            }
            //
            GET_request = sb.ToString();
            wRequest = WebRequest.Create( GET_request ) as HttpWebRequest;
            wRequest.Method = "GET";
            request = GET_request;
         }
         else
         {
            // -- POST --
            string POST_request = sb.ToString();
            request = POST_request + " <|| POST:: " + apiHelper.DictionaryToString( parameters ) + " ||>";
            //
            wRequest = WebRequest.Create( POST_request ) as HttpWebRequest;
            wRequest.Method = "POST";
            wRequest.ContentType = "application/x-www-form-urlencoded";
            //
            int index = 0;
            string[] encodedParameters = new string[parameters.Count];
            foreach ( KeyValuePair<string, string> parameter in parameters )
            {
               encodedParameters[index++] = HttpUtility.UrlEncode( parameter.Key ) + "=" + HttpUtility.UrlEncode( parameter.Value );
            }
            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] requestData = encoding.GetBytes( string.Join( "&", encodedParameters ) );
            wRequest.ContentLength = requestData.Length;
            //
            Stream stream = wRequest.GetRequestStream();
            stream.Write( requestData, 0, requestData.Length );
            stream.Close();
         }
         // ===============================================================
         // same for both...
         // ------------------------------- Get the response
         //
         HttpWebResponse wResponse = wRequest.GetResponse() as HttpWebResponse;

         StreamReader reader = new StreamReader( wResponse.GetResponseStream() );
         string APIResponse = reader.ReadToEnd();

         wResponse.Close();
         reader.Close();

         APIResponse = APIResponse.Replace( ">\n<", "><" );  // get rid of the new lines
         return APIResponse;
      }

      #region ------------------------------------------------------------ common use

      // ---------------------------------------------------------------------------- FormatMemberMergeVars
      internal static Dictionary<string, string> FormatMemberMergeVars( Dictionary<string, object> merge_vars )
      {
         Dictionary<string, string> MergeVars = new Dictionary<string, string>();
         //
         foreach ( KeyValuePair<string, object> kv in merge_vars )
         {
            if ( kv.Key.ToLower().Contains( "groupings" ) )
            {
               int ix = -1;
               List<interestGroupings> igList = kv.Value as List<interestGroupings>;
               //
               foreach ( interestGroupings ig in igList )
               {
                  ix++;
                  string groups = "";
                  if ( ig.groups.Count > 0 )
                     groups = apiHelper.MakeStringFromList( ig.groups );
                  if ( ig.id > 0 )
                     MergeVars.Add( string.Format( "[groupings][{0}][{1}]", ix, "id" ), ig.id.ToString() ?? "" );
                  if ( !string.IsNullOrEmpty( ig.name ) )
                     MergeVars.Add( string.Format( "[groupings][{0}][{1}]", ix, "name" ), ig.name ?? "" );
                  MergeVars.Add( string.Format( "[groupings][{0}][{1}]", ix, "groups" ), groups );
               }
            }
            else if ( kv.Value.GetType().Name.ToLower().Contains( "dictionary" ) )
            {
               foreach ( KeyValuePair<string, object> kvp in kv.Value as Dictionary<string, object> )
               {
                  MergeVars.Add( string.Format( "[{0}][{1}]", kv.Key, kvp.Key ), kvp.Value.ToString() ?? "" );
               }
            }
            else if ( kv.Value.GetType().Name.ToLower().Contains( "datetime" ) )
            {
               DateTime dt = (DateTime)kv.Value;
               MergeVars.Add( string.Format( "[{0}]", kv.Key ), apiHelper.FormatApiDateParm( dt ) );
            }
            else
               MergeVars.Add( string.Format( "[{0}]", kv.Key ), kv.Value.ToString() ?? "" );
         }
         //
         return MergeVars;
      }

      // ---------------------------------------------------------------------------- GetXmlOutputError
      internal static Api_Error GetXmlOutputError( XElement xml )
      {
         // NOTE: api_BaseOutput allows for multiple errors in future, but MC only returns one for now...
         if ( xml.Descendants( "error" ).Count() > 0 )
         {
            // -------- only 1 for now, so don't sweat the small stuff
            Api_Error aError = new Api_Error();
            aError.error = xml.Element( "error" ).Value ?? "";
            aError.code = xml.Element( "code" ).Value ?? "";
            // 
            return aError;
         }
         else
            return null;
      }

      #endregion
   }
}
